﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NIDViewer
{
    public class ConfigParser
    {
        private Dictionary<string, Dictionary<string, string>> _sections = new Dictionary<string, Dictionary<string, string>>();
        private HashSet<string> _inlineCommentPrefixes = new HashSet<string> { "#", ";" };
        private HashSet<string> _commentPrefixes = new HashSet<string> { "#", ";" };
        private string _defaultSection = "DEFAULT";
        private bool _strict = true;

        public Dictionary<string, string> this[string key]
        {
            get => _sections[key];
        }

        public bool ContainsKey(string key)
        {
            return _sections.ContainsKey(key);
        }

        public void ReadString(string str)
        {
            using StringReader sfile = new(str);
            ReadFile(sfile, "<string>");
        }

        public void ReadFile(TextReader reader, string source)
        {
            Read(reader, source);
        }

        private void Read(TextReader reader, string source)
        {
            var elementsAdded = new HashSet<(string, string)>();
            Dictionary<string, string> cursect = null;
            string sectname = null;
            string optname = null;
            int lineno = 0;
            int indentLevel = 0;

            string line;
            while ((line = reader.ReadLine()) != null)
            {
                lineno++;
                int commentStart = int.MaxValue;

                // Strip inline comments  
                foreach (var prefix in _inlineCommentPrefixes)
                {
                    int index = line.IndexOf(prefix);
                    if (index >= 0 && (index == 0 || char.IsWhiteSpace(line[index - 1])))
                    {
                        commentStart = Math.Min(commentStart, index);
                    }
                }

                // Strip full line comments  
                foreach (var prefix in _commentPrefixes)
                {
                    if (line.TrimStart().StartsWith(prefix))
                    {
                        commentStart = 0;
                        break;
                    }
                }

                string value = commentStart < int.MaxValue ? line.Substring(0, commentStart).Trim() : line.Trim();
                if (string.IsNullOrEmpty(value))
                {
                    continue;
                }

                // Check for section header  
                if (value.StartsWith("[") && value.EndsWith("]"))
                {
                    sectname = value.Substring(1, value.Length - 2).Trim();
                    if (!_sections.ContainsKey(sectname))
                    {
                        _sections[sectname] = new Dictionary<string, string>();
                    }
                    cursect = _sections[sectname];
                    optname = null;
                }
                // Check for option line  
                else if (cursect != null)
                {
                    var parts = value.Split(new[] { '=', ':' }, 2);
                    if (parts.Length == 2)
                    {
                        optname = parts[0].Trim();
                        string optval = parts[1].Trim();
                        //if (!cursect.ContainsKey(optname))
                        //{
                        //    cursect[optname] = new List<string>();
                        //}
                        cursect[optname] = optval;
                    }
                }
                else
                {
                    throw new Exception($"Missing section header in {source} at line {lineno}");
                }
            }
        }
    }
}
